/*
* Copyright (c) Huawei Technologies Co., Ltd. 2022. All rights reserved.
*/

#include "vpc_pipe_csc.h"
#include "dvpp_cmdlist_define.h"
#include "dvpp_cmdlist_num_define.h"

static const vpc_pic_fmt_e g_yuv_field[] = {
    YUV420_SEMI_PLANNAR, YUV422_SEMI_PLANNAR, YUV444_SEMI_PLANNAR, YUV440_SEMI_PLANNAR, YUV411_SEMI_PLANNAR,
    YUV420_PLANNAR,      YUV422_PLANNAR,      YUV444_PLANNAR,      YUV440_PLANNAR,      YUV411_PLANNAR,
    YUV422_PACKED,       YUV444_PACKED,       XYUV444_PACKED};

static const vpc_pic_fmt_e g_rgb_field[] = {RGB888_PLANNAR, RGB888_PACKED, XRGB8888_PACKED};

static const vpc_pic_fmt_e g_gray_field[] = {YUV400};

static const vpc_pic_fmt_e g_rgb_fp32_field[] = {
    RGB888_PLANNAR_FP16,  RGB888_PLANNAR_FP32,   RGB888_PLANNAR_BF16,   RGB888_PLANNAR_INT16,  RGB888_PLANNAR_INT32,
    RGB888_PLANNAR_INT64, RGB888_PLANNAR_UINT16, RGB888_PLANNAR_UINT32, RGB888_PLANNAR_UINT64, RGB888_PLANNAR_INT8,
    RGB888_PACKED_FP16,   RGB888_PACKED_FP32,    RGB888_PACKED_BF16,    RGB888_PACKED_INT16,   RGB888_PACKED_INT32,
    RGB888_PACKED_UINT16, RGB888_PACKED_UINT32,  RGB888_PACKED_INT8,
};

static const vpc_pic_fmt_e g_gray_fp32_field[] = {
    YUV400_FP16,  YUV400_FP32,   YUV400_FP64,   YUV400_BF16,   YUV400_INT16, YUV400_INT32,
    YUV400_INT64, YUV400_UINT16, YUV400_UINT32, YUV400_UINT64, YUV400_INT8,
};

static const vpc_pic_fmt_e g_fp32_field[] = {
    RGB888_PLANNAR_FP32, RGB888_PACKED_FP32, YUV400_FP32
};

static uint8_t find_fmt(const vpc_pic_fmt_e *field, const uint32_t len, const vpc_pic_fmt_e target)
{
    uint32_t i;
    for (i = 0; i < len; i++) {
        if (field[i] == target) {
            return 1;
        }
    }

    return 0;
}

/******************************YUV_TO_RGB******************************/
#define YUV_TO_RGB_COEFFCIENT_0 0x1000000ULL
#define YUV_TO_RGB_COEFFCIENT_1 0x0ULL
#define YUV_TO_RGB_COEFFCIENT_2 0x166E900ULL
#define YUV_TO_RGB_COEFFCIENT_3 0x1000000ULL
#define YUV_TO_RGB_COEFFCIENT_4 0xFFFFA7E600ULL
#define YUV_TO_RGB_COEFFCIENT_5 0xFFFF492E00ULL
#define YUV_TO_RGB_COEFFCIENT_6 0x1000000ULL
#define YUV_TO_RGB_COEFFCIENT_7 0x1C5A200ULL
#define YUV_TO_RGB_COEFFCIENT_8 0x0ULL
#define YUV_TO_RGB_OFFSET_0 0xFF4C8B8000ULL
#define YUV_TO_RGB_OFFSET_1 0x87760000ULL
#define YUV_TO_RGB_OFFSET_2 0xFF1D2F0000ULL

static uint8_t judge_support_yuv_to_rgb(vpc_pic_fmt_e infmt, vpc_pic_fmt_e outfmt)
{
    return ((find_fmt(g_yuv_field, sizeof(g_yuv_field) / sizeof(vpc_pic_fmt_e), infmt)) &&
           (find_fmt(g_rgb_field, sizeof(g_rgb_field) / sizeof(vpc_pic_fmt_e), outfmt)));
}

static color_conv_t g_yuv_to_rgb = {
    .type = YUV_TO_RGB,
    .coeff = {
        GET_LOW_ADDR(YUV_TO_RGB_COEFFCIENT_0), GET_HIGH_ADDR(YUV_TO_RGB_COEFFCIENT_0),
        GET_LOW_ADDR(YUV_TO_RGB_COEFFCIENT_1), GET_HIGH_ADDR(YUV_TO_RGB_COEFFCIENT_1),
        GET_LOW_ADDR(YUV_TO_RGB_COEFFCIENT_2), GET_HIGH_ADDR(YUV_TO_RGB_COEFFCIENT_2),
        GET_LOW_ADDR(YUV_TO_RGB_COEFFCIENT_3), GET_HIGH_ADDR(YUV_TO_RGB_COEFFCIENT_3),
        GET_LOW_ADDR(YUV_TO_RGB_COEFFCIENT_4), GET_HIGH_ADDR(YUV_TO_RGB_COEFFCIENT_4),
        GET_LOW_ADDR(YUV_TO_RGB_COEFFCIENT_5), GET_HIGH_ADDR(YUV_TO_RGB_COEFFCIENT_5),
        GET_LOW_ADDR(YUV_TO_RGB_COEFFCIENT_6), GET_HIGH_ADDR(YUV_TO_RGB_COEFFCIENT_6),
        GET_LOW_ADDR(YUV_TO_RGB_COEFFCIENT_7), GET_HIGH_ADDR(YUV_TO_RGB_COEFFCIENT_7),
        GET_LOW_ADDR(YUV_TO_RGB_COEFFCIENT_8), GET_HIGH_ADDR(YUV_TO_RGB_COEFFCIENT_8),
        GET_LOW_ADDR(YUV_TO_RGB_OFFSET_0),     GET_HIGH_ADDR(YUV_TO_RGB_OFFSET_0),
        GET_LOW_ADDR(YUV_TO_RGB_OFFSET_1),     GET_HIGH_ADDR(YUV_TO_RGB_OFFSET_1),
        GET_LOW_ADDR(YUV_TO_RGB_OFFSET_2),     GET_HIGH_ADDR(YUV_TO_RGB_OFFSET_2),
    },
    .pfn_judge_support = judge_support_yuv_to_rgb,
};

static uint64_t VUY_TO_BGR_COEFF[9][12] = {
    {0x1000000,    0x0,          0x166E900,
        0x1000000,    0xFFFFA7E600U, 0xFFFF492E00U,
        0x1000000,    0x1C5A200,    0x0,
        0xFF4C8B8000U, 0x87760000U,   0xFF1D2F0000U}, // BT601 full range 3位小数 // equals to VUY_TO_BGR matrix
    {0x12a14cf,    0x0,          0x198956c,
        0x12a14cf,    0xffff9bb59eU, 0xffff2fe133U,
        0x12a14cf,    0x204692f,    0x0,
        0xff2113fd0dU, 0x87934acbU,   0xfeeb2a1b5cU}, // BT601 narrow range 5位小数
    {0x1000000,    0x0,          0x1932618,
        0x1000000,    0xffffd00bccU, 0xffff88294aU,
        0x1000000,    0x1db089a,    0x0,
        0xff366cf41fU, 0x53e5753a,   0xff127bb2ffU}, // BT709 full range 5位小数
    {0x12a14cf,    0x0,          0x1caf102,
        0x12a14cf,    0xffffc96873U, 0xffff779336U,
        0x12a14cf,    0x21cc63f,    0x0,
        0xff07e631f9U, 0x4ce0ded3,   0xfedefb938aU}, // BT709 narrow range 5位小数
    {0x1000000,    0x0,          0x1797f63,
        0x1000000,    0xffffd5e00dU, 0xffff6dbc02U,
        0x1000000,    0x1e1a36e,    0x0,
        0xff43404ea5U, 0x5e31f8a1,   0xff0f2e48e9U}, // BT2020 full range 5位小数
    {0x12a14cf,    0x0,          0x1adbd51,
        0x12a14cf,    0xffffd00b24U, 0xffff597e13U,
        0x12a14cf,    0x2244b0a,    0x0,
        0xff16800a7cU, 0x589a176e,   0xfedb392e1fU}, // BT2020 narrow range 5位小数
    // ┌ B ┐   ┌ 2  1  0 ┐   ┌ V ┐   ┌ 9 ┐
    // │ G │ = │ 5  4  3 │ * │ U │ + │ 10│
    // └ R ┘   └ 8  7  6 ┘   └ Y ┘   └ 11┘
    {0x1000000,     0x0,             0x166E900,
        0x1000000,     0xFFFFA7E600U,   0xFFFF492E00U,
        0x1000000,     0x1C5A200,       0x0,
        0xFF4C8B8000U, 0x87760000U,    0xFF1D2F0000U}, // NUM_6: VUY_TO_BGR
    {0x1000000,     0x166E900,       0x0,
        0x1000000,     0xFFFF492E00U,   0xFFFFA7E600U,
        0x1000000,     0x0,             0x1C5A200,
        0xFF4C8B8000U, 0x87760000U,    0xFF1D2F0000U}, // NUM_7: UVY_TO_BGR
    {0x166E900,     0x0,            0x1000000,
        0xFFFF492E00U, 0xFFFFA7E600U,  0x1000000,
        0x0,           0x1C5A200,      0x1000000,
        0xFF4C8B8000U, 0x87760000U,    0xFF1D2F0000U}, // NUM_8: YUV_TO_BGR
};
/******************************YUV_TO_RGB******************************/


/******************************RGB_TO_YUV******************************/
#define RGB_TO_YUV_COEFFCIENT_0 0x4C8B00ULL
#define RGB_TO_YUV_COEFFCIENT_1 0x964600ULL
#define RGB_TO_YUV_COEFFCIENT_2 0x1D2F00ULL
#define RGB_TO_YUV_COEFFCIENT_3 0xFFFFD4CD00ULL
#define RGB_TO_YUV_COEFFCIENT_4 0xFFFFAB3300ULL
#define RGB_TO_YUV_COEFFCIENT_5 0x800000ULL
#define RGB_TO_YUV_COEFFCIENT_6 0x800000ULL
#define RGB_TO_YUV_COEFFCIENT_7 0xFFFF94D100ULL
#define RGB_TO_YUV_COEFFCIENT_8 0xFFFFEB2F00ULL
#define RGB_TO_YUV_OFFSET_0 0xFFFF800000ULL
#define RGB_TO_YUV_OFFSET_1 0x7F800000ULL
#define RGB_TO_YUV_OFFSET_2 0x7F800000ULL

static uint8_t judge_support_rgb_to_yuv(vpc_pic_fmt_e infmt, vpc_pic_fmt_e outfmt)
{
    return ((find_fmt(g_rgb_field, sizeof(g_rgb_field) / sizeof(vpc_pic_fmt_e), infmt)) &&
           (find_fmt(g_yuv_field, sizeof(g_yuv_field) / sizeof(vpc_pic_fmt_e), outfmt)));
}

static color_conv_t g_rgb_to_yuv = {
    .type = RGB_TO_YUV,
    .coeff = {
        GET_LOW_ADDR(RGB_TO_YUV_COEFFCIENT_0), GET_HIGH_ADDR(RGB_TO_YUV_COEFFCIENT_0),
        GET_LOW_ADDR(RGB_TO_YUV_COEFFCIENT_1), GET_HIGH_ADDR(RGB_TO_YUV_COEFFCIENT_1),
        GET_LOW_ADDR(RGB_TO_YUV_COEFFCIENT_2), GET_HIGH_ADDR(RGB_TO_YUV_COEFFCIENT_2),
        GET_LOW_ADDR(RGB_TO_YUV_COEFFCIENT_3), GET_HIGH_ADDR(RGB_TO_YUV_COEFFCIENT_3),
        GET_LOW_ADDR(RGB_TO_YUV_COEFFCIENT_4), GET_HIGH_ADDR(RGB_TO_YUV_COEFFCIENT_4),
        GET_LOW_ADDR(RGB_TO_YUV_COEFFCIENT_5), GET_HIGH_ADDR(RGB_TO_YUV_COEFFCIENT_5),
        GET_LOW_ADDR(RGB_TO_YUV_COEFFCIENT_6), GET_HIGH_ADDR(RGB_TO_YUV_COEFFCIENT_6),
        GET_LOW_ADDR(RGB_TO_YUV_COEFFCIENT_7), GET_HIGH_ADDR(RGB_TO_YUV_COEFFCIENT_7),
        GET_LOW_ADDR(RGB_TO_YUV_COEFFCIENT_8), GET_HIGH_ADDR(RGB_TO_YUV_COEFFCIENT_8),
        GET_LOW_ADDR(RGB_TO_YUV_OFFSET_0),     GET_HIGH_ADDR(RGB_TO_YUV_OFFSET_0),
        GET_LOW_ADDR(RGB_TO_YUV_OFFSET_1),     GET_HIGH_ADDR(RGB_TO_YUV_OFFSET_1),
        GET_LOW_ADDR(RGB_TO_YUV_OFFSET_2),     GET_HIGH_ADDR(RGB_TO_YUV_OFFSET_2),
    },
    .pfn_judge_support = judge_support_rgb_to_yuv,
};

static uint64_t RGB_TO_YUV_COEFF[6][12] = {
    {0x4C8B00,     0x964600,     0x1D2F00,
        0xFFFFD4CD00U, 0xFFFFAB3300U, 0x800000,
        0x800000,     0xFFFF94D100U, 0xFFFFEB2F00U,
        0xFFFF800000U, 0x7F800000,   0x7F800000}, // BT601 full range 3位小数, 当前offeset是-0.5 127.5 127.5
    {0x41bc00,     0x810e00,     0x191000,
        0xffffda7600U, 0xffffb59000U, 0x707000,
        0x707000,     0xffffa1c600U, 0xffffedc800U,
        0x10000000,   0x80000000U,   0x80000000U}, // BT601 narrow range 5位小数
    {0x366cf4,     0xb71759,     0x127bb3,
        0xffffe2ab8aU, 0xffff9d5476U, 0x800000,
        0x800000,     0xffff8bbcd3U, 0xfffff4432dU,
        0x0,          0x80000000U,   0x80000000U}, // BT709 full range 5位小数
    {0x2ebe00,     0x9d3e00,     0xfe000,
        0xffffe63c00U, 0xffffa95400U, 0x707000,
        0x707000,     0xffff99de00U, 0xfffff5b000U,
        0x10000000,   0x80000000U,   0x80000000U}, // BT709 narrow range 5位小数
    {0x43404f,     0xad9168,     0xf2e49,
        0xffffdc4135U, 0xffffa3becbU, 0x800000,
        0x800000,     0xffff8a4b34U, 0xfffff5b4ccU,
        0x0,          0x80000000U,   0x80000000U}, // BT2020 full range 5位小数
    {0x39c200,     0x951000,     0xd0a00,
        0xffffe09a00U, 0xffffaef600U, 0x707000,
        0x707000,     0xffff989a00U, 0xfffff6f400U,
        0x10000000,   0x80000000U,   0x80000000U}, // BT2020 full range 5位小数
};
/******************************RGB_TO_YUV******************************/

/******************************RGB_TO_GRAY******************************/
#define RGB_TO_GRAY_COEFFCIENT_0 0x0ULL
#define RGB_TO_GRAY_COEFFCIENT_1 0x0ULL
#define RGB_TO_GRAY_COEFFCIENT_2 0x0ULL
#define RGB_TO_GRAY_COEFFCIENT_3 0x0ULL
#define RGB_TO_GRAY_COEFFCIENT_4 0x0ULL
#define RGB_TO_GRAY_COEFFCIENT_5 0x0ULL
#define RGB_TO_GRAY_COEFFCIENT_6 0x4C8B00ULL
#define RGB_TO_GRAY_COEFFCIENT_7 0x964600ULL
#define RGB_TO_GRAY_COEFFCIENT_8 0x1D2F00ULL
#define RGB_TO_GRAY_OFFSET_0 0x0ULL
#define RGB_TO_GRAY_OFFSET_1 0x0ULL
#define RGB_TO_GRAY_OFFSET_2 0xFFFF800000ULL

static uint8_t judge_support_rgb_to_gray(vpc_pic_fmt_e infmt, vpc_pic_fmt_e outfmt)
{
    return ((find_fmt(g_rgb_field, sizeof(g_rgb_field) / sizeof(vpc_pic_fmt_e), infmt)) &&
           (find_fmt(g_gray_field, sizeof(g_gray_field) / sizeof(vpc_pic_fmt_e), outfmt)));
}

static color_conv_t g_rgb_to_gray = {
    .type = RGB_TO_GRAY,
    .coeff = {
        GET_LOW_ADDR(RGB_TO_GRAY_COEFFCIENT_0), GET_HIGH_ADDR(RGB_TO_GRAY_COEFFCIENT_0),
        GET_LOW_ADDR(RGB_TO_GRAY_COEFFCIENT_1), GET_HIGH_ADDR(RGB_TO_GRAY_COEFFCIENT_1),
        GET_LOW_ADDR(RGB_TO_GRAY_COEFFCIENT_2), GET_HIGH_ADDR(RGB_TO_GRAY_COEFFCIENT_2),
        GET_LOW_ADDR(RGB_TO_GRAY_COEFFCIENT_3), GET_HIGH_ADDR(RGB_TO_GRAY_COEFFCIENT_3),
        GET_LOW_ADDR(RGB_TO_GRAY_COEFFCIENT_4), GET_HIGH_ADDR(RGB_TO_GRAY_COEFFCIENT_4),
        GET_LOW_ADDR(RGB_TO_GRAY_COEFFCIENT_5), GET_HIGH_ADDR(RGB_TO_GRAY_COEFFCIENT_5),
        GET_LOW_ADDR(RGB_TO_GRAY_COEFFCIENT_6), GET_HIGH_ADDR(RGB_TO_GRAY_COEFFCIENT_6),
        GET_LOW_ADDR(RGB_TO_GRAY_COEFFCIENT_7), GET_HIGH_ADDR(RGB_TO_GRAY_COEFFCIENT_7),
        GET_LOW_ADDR(RGB_TO_GRAY_COEFFCIENT_8), GET_HIGH_ADDR(RGB_TO_GRAY_COEFFCIENT_8),
        GET_LOW_ADDR(RGB_TO_GRAY_OFFSET_0),     GET_HIGH_ADDR(RGB_TO_GRAY_OFFSET_0),
        GET_LOW_ADDR(RGB_TO_GRAY_OFFSET_1),     GET_HIGH_ADDR(RGB_TO_GRAY_OFFSET_1),
        GET_LOW_ADDR(RGB_TO_GRAY_OFFSET_2),     GET_HIGH_ADDR(RGB_TO_GRAY_OFFSET_2),
    },
    .pfn_judge_support = judge_support_rgb_to_gray,
};
/******************************RGB_TO_GRAY******************************/

/******************************GRAY_TO_RGB******************************/
#define GRAY_TO_RGB_COEFFCIENT_0 0x0ULL
#define GRAY_TO_RGB_COEFFCIENT_1 0x0ULL
#define GRAY_TO_RGB_COEFFCIENT_2 0x1000000ULL
#define GRAY_TO_RGB_COEFFCIENT_3 0x0ULL
#define GRAY_TO_RGB_COEFFCIENT_4 0x0ULL
#define GRAY_TO_RGB_COEFFCIENT_5 0x1000000ULL
#define GRAY_TO_RGB_COEFFCIENT_6 0x0ULL
#define GRAY_TO_RGB_COEFFCIENT_7 0x0ULL
#define GRAY_TO_RGB_COEFFCIENT_8 0x1000000ULL
#define GRAY_TO_RGB_OFFSET_0 0x0ULL
#define GRAY_TO_RGB_OFFSET_1 0x0ULL
#define GRAY_TO_RGB_OFFSET_2 0x0ULL

static uint8_t judge_support_gray_to_rgb(vpc_pic_fmt_e infmt, vpc_pic_fmt_e outfmt)
{
    return ((find_fmt(g_gray_field, sizeof(g_gray_field) / sizeof(vpc_pic_fmt_e), infmt)) &&
           (find_fmt(g_rgb_field, sizeof(g_rgb_field) / sizeof(vpc_pic_fmt_e), outfmt)));
}

static color_conv_t g_gray_to_rgb = {
    .type = GRAY_TO_RGB,
    .coeff = {
        GET_LOW_ADDR(GRAY_TO_RGB_COEFFCIENT_0), GET_HIGH_ADDR(GRAY_TO_RGB_COEFFCIENT_0),
        GET_LOW_ADDR(GRAY_TO_RGB_COEFFCIENT_1), GET_HIGH_ADDR(GRAY_TO_RGB_COEFFCIENT_1),
        GET_LOW_ADDR(GRAY_TO_RGB_COEFFCIENT_2), GET_HIGH_ADDR(GRAY_TO_RGB_COEFFCIENT_2),
        GET_LOW_ADDR(GRAY_TO_RGB_COEFFCIENT_3), GET_HIGH_ADDR(GRAY_TO_RGB_COEFFCIENT_3),
        GET_LOW_ADDR(GRAY_TO_RGB_COEFFCIENT_4), GET_HIGH_ADDR(GRAY_TO_RGB_COEFFCIENT_4),
        GET_LOW_ADDR(GRAY_TO_RGB_COEFFCIENT_5), GET_HIGH_ADDR(GRAY_TO_RGB_COEFFCIENT_5),
        GET_LOW_ADDR(GRAY_TO_RGB_COEFFCIENT_6), GET_HIGH_ADDR(GRAY_TO_RGB_COEFFCIENT_6),
        GET_LOW_ADDR(GRAY_TO_RGB_COEFFCIENT_7), GET_HIGH_ADDR(GRAY_TO_RGB_COEFFCIENT_7),
        GET_LOW_ADDR(GRAY_TO_RGB_COEFFCIENT_8), GET_HIGH_ADDR(GRAY_TO_RGB_COEFFCIENT_8),
        GET_LOW_ADDR(GRAY_TO_RGB_OFFSET_0),     GET_HIGH_ADDR(GRAY_TO_RGB_OFFSET_0),
        GET_LOW_ADDR(GRAY_TO_RGB_OFFSET_1),     GET_HIGH_ADDR(GRAY_TO_RGB_OFFSET_1),
        GET_LOW_ADDR(GRAY_TO_RGB_OFFSET_2),     GET_HIGH_ADDR(GRAY_TO_RGB_OFFSET_2),
    },
    .pfn_judge_support = judge_support_gray_to_rgb,
};
/******************************GRAY_TO_RGB******************************/

/******************************YUV_TO_GRAY******************************/
#define YUV_TO_GRAY_COEFFCIENT_0 0x0ULL
#define YUV_TO_GRAY_COEFFCIENT_1 0x0ULL
#define YUV_TO_GRAY_COEFFCIENT_2 0x0ULL
#define YUV_TO_GRAY_COEFFCIENT_3 0x0ULL
#define YUV_TO_GRAY_COEFFCIENT_4 0x0ULL
#define YUV_TO_GRAY_COEFFCIENT_5 0x0ULL
#define YUV_TO_GRAY_COEFFCIENT_6 0x1000000ULL
#define YUV_TO_GRAY_COEFFCIENT_7 0x0ULL
#define YUV_TO_GRAY_COEFFCIENT_8 0x0ULL
#define YUV_TO_GRAY_OFFSET_0 0x0ULL
#define YUV_TO_GRAY_OFFSET_1 0x0ULL
#define YUV_TO_GRAY_OFFSET_2 0x0ULL

static uint8_t judge_support_yuv_to_gray(vpc_pic_fmt_e infmt, vpc_pic_fmt_e outfmt)
{
    return ((find_fmt(g_yuv_field, sizeof(g_yuv_field) / sizeof(vpc_pic_fmt_e), infmt)) &&
           (find_fmt(g_gray_field, sizeof(g_gray_field) / sizeof(vpc_pic_fmt_e), outfmt)));
}

static color_conv_t g_yuv_to_gray = {
    .type = YUV_TO_GRAY,
    .coeff = {
        GET_LOW_ADDR(YUV_TO_GRAY_COEFFCIENT_0), GET_HIGH_ADDR(YUV_TO_GRAY_COEFFCIENT_0),
        GET_LOW_ADDR(YUV_TO_GRAY_COEFFCIENT_1), GET_HIGH_ADDR(YUV_TO_GRAY_COEFFCIENT_1),
        GET_LOW_ADDR(YUV_TO_GRAY_COEFFCIENT_2), GET_HIGH_ADDR(YUV_TO_GRAY_COEFFCIENT_2),
        GET_LOW_ADDR(YUV_TO_GRAY_COEFFCIENT_3), GET_HIGH_ADDR(YUV_TO_GRAY_COEFFCIENT_3),
        GET_LOW_ADDR(YUV_TO_GRAY_COEFFCIENT_4), GET_HIGH_ADDR(YUV_TO_GRAY_COEFFCIENT_4),
        GET_LOW_ADDR(YUV_TO_GRAY_COEFFCIENT_5), GET_HIGH_ADDR(YUV_TO_GRAY_COEFFCIENT_5),
        GET_LOW_ADDR(YUV_TO_GRAY_COEFFCIENT_6), GET_HIGH_ADDR(YUV_TO_GRAY_COEFFCIENT_6),
        GET_LOW_ADDR(YUV_TO_GRAY_COEFFCIENT_7), GET_HIGH_ADDR(YUV_TO_GRAY_COEFFCIENT_7),
        GET_LOW_ADDR(YUV_TO_GRAY_COEFFCIENT_8), GET_HIGH_ADDR(YUV_TO_GRAY_COEFFCIENT_8),
        GET_LOW_ADDR(YUV_TO_GRAY_OFFSET_0),     GET_HIGH_ADDR(YUV_TO_GRAY_OFFSET_0),
        GET_LOW_ADDR(YUV_TO_GRAY_OFFSET_1),     GET_HIGH_ADDR(YUV_TO_GRAY_OFFSET_1),
        GET_LOW_ADDR(YUV_TO_GRAY_OFFSET_2),     GET_HIGH_ADDR(YUV_TO_GRAY_OFFSET_2),
    },
    .pfn_judge_support = judge_support_yuv_to_gray,
};
/******************************YUV_TO_GRAY******************************/

/******************************GRAY_TO_YUV******************************/
#define GRAY_TO_YUV_COEFFCIENT_0 0x0ULL
#define GRAY_TO_YUV_COEFFCIENT_1 0x0ULL
#define GRAY_TO_YUV_COEFFCIENT_2 0x1000000ULL
#define GRAY_TO_YUV_COEFFCIENT_3 0x0ULL
#define GRAY_TO_YUV_COEFFCIENT_4 0x0ULL
#define GRAY_TO_YUV_COEFFCIENT_5 0x0ULL
#define GRAY_TO_YUV_COEFFCIENT_6 0x0ULL
#define GRAY_TO_YUV_COEFFCIENT_7 0x0ULL
#define GRAY_TO_YUV_COEFFCIENT_8 0x0ULL
#define GRAY_TO_YUV_OFFSET_0 0x0ULL
#define GRAY_TO_YUV_OFFSET_1 0x80000000ULL
#define GRAY_TO_YUV_OFFSET_2 0x80000000ULL

static uint8_t judge_support_gray_to_yuv(vpc_pic_fmt_e infmt, vpc_pic_fmt_e outfmt)
{
    return ((find_fmt(g_gray_field, sizeof(g_gray_field) / sizeof(vpc_pic_fmt_e), infmt)) &&
           (find_fmt(g_yuv_field, sizeof(g_yuv_field) / sizeof(vpc_pic_fmt_e), outfmt)));
}

static color_conv_t g_gray_to_yuv = {
    .type = GRAY_TO_YUV,
    .coeff = {
        GET_LOW_ADDR(GRAY_TO_YUV_COEFFCIENT_0), GET_HIGH_ADDR(GRAY_TO_YUV_COEFFCIENT_0),
        GET_LOW_ADDR(GRAY_TO_YUV_COEFFCIENT_1), GET_HIGH_ADDR(GRAY_TO_YUV_COEFFCIENT_1),
        GET_LOW_ADDR(GRAY_TO_YUV_COEFFCIENT_2), GET_HIGH_ADDR(GRAY_TO_YUV_COEFFCIENT_2),
        GET_LOW_ADDR(GRAY_TO_YUV_COEFFCIENT_3), GET_HIGH_ADDR(GRAY_TO_YUV_COEFFCIENT_3),
        GET_LOW_ADDR(GRAY_TO_YUV_COEFFCIENT_4), GET_HIGH_ADDR(GRAY_TO_YUV_COEFFCIENT_4),
        GET_LOW_ADDR(GRAY_TO_YUV_COEFFCIENT_5), GET_HIGH_ADDR(GRAY_TO_YUV_COEFFCIENT_5),
        GET_LOW_ADDR(GRAY_TO_YUV_COEFFCIENT_6), GET_HIGH_ADDR(GRAY_TO_YUV_COEFFCIENT_6),
        GET_LOW_ADDR(GRAY_TO_YUV_COEFFCIENT_7), GET_HIGH_ADDR(GRAY_TO_YUV_COEFFCIENT_7),
        GET_LOW_ADDR(GRAY_TO_YUV_COEFFCIENT_8), GET_HIGH_ADDR(GRAY_TO_YUV_COEFFCIENT_8),
        GET_LOW_ADDR(GRAY_TO_YUV_OFFSET_0),     GET_HIGH_ADDR(GRAY_TO_YUV_OFFSET_0),
        GET_LOW_ADDR(GRAY_TO_YUV_OFFSET_1),     GET_HIGH_ADDR(GRAY_TO_YUV_OFFSET_1),
        GET_LOW_ADDR(GRAY_TO_YUV_OFFSET_2),     GET_HIGH_ADDR(GRAY_TO_YUV_OFFSET_2),
    },
    .pfn_judge_support = judge_support_gray_to_yuv,
};
/******************************GRAY_TO_YUV******************************/

/******************************RGB_FP32_TO_GRAY******************************/
#define RGB_FP32_TO_GRAY_COEFFCIENT_0 0x0ULL
#define RGB_FP32_TO_GRAY_COEFFCIENT_1 0x0ULL
#define RGB_FP32_TO_GRAY_COEFFCIENT_2 0x0ULL
#define RGB_FP32_TO_GRAY_COEFFCIENT_3 0x0ULL
#define RGB_FP32_TO_GRAY_COEFFCIENT_4 0x0ULL
#define RGB_FP32_TO_GRAY_COEFFCIENT_5 0x0ULL
#define RGB_FP32_TO_GRAY_COEFFCIENT_6 0x3E991687ULL
#define RGB_FP32_TO_GRAY_COEFFCIENT_7 0x3F1645A1ULL
#define RGB_FP32_TO_GRAY_COEFFCIENT_8 0x3DE978D4ULL
#define RGB_FP32_TO_GRAY_OFFSET_0 0x0ULL
#define RGB_FP32_TO_GRAY_OFFSET_1 0x0ULL
#define RGB_FP32_TO_GRAY_OFFSET_2 0x0ULL

static uint8_t judge_support_rgbfp32_to_gray(vpc_pic_fmt_e infmt, vpc_pic_fmt_e outfmt)
{
    return ((find_fmt(g_rgb_fp32_field, sizeof(g_rgb_fp32_field) / sizeof(vpc_pic_fmt_e), infmt)) &&
           (find_fmt(g_gray_field, sizeof(g_gray_field) / sizeof(vpc_pic_fmt_e), outfmt)));
}

static color_conv_t g_rgbfp32_to_gray = {
    .type = RGB_FP32_TO_GRAY,
    .coeff = {
        GET_LOW_ADDR(RGB_FP32_TO_GRAY_COEFFCIENT_0), GET_HIGH_ADDR(RGB_FP32_TO_GRAY_COEFFCIENT_0),
        GET_LOW_ADDR(RGB_FP32_TO_GRAY_COEFFCIENT_1), GET_HIGH_ADDR(RGB_FP32_TO_GRAY_COEFFCIENT_1),
        GET_LOW_ADDR(RGB_FP32_TO_GRAY_COEFFCIENT_2), GET_HIGH_ADDR(RGB_FP32_TO_GRAY_COEFFCIENT_2),
        GET_LOW_ADDR(RGB_FP32_TO_GRAY_COEFFCIENT_3), GET_HIGH_ADDR(RGB_FP32_TO_GRAY_COEFFCIENT_3),
        GET_LOW_ADDR(RGB_FP32_TO_GRAY_COEFFCIENT_4), GET_HIGH_ADDR(RGB_FP32_TO_GRAY_COEFFCIENT_4),
        GET_LOW_ADDR(RGB_FP32_TO_GRAY_COEFFCIENT_5), GET_HIGH_ADDR(RGB_FP32_TO_GRAY_COEFFCIENT_5),
        GET_LOW_ADDR(RGB_FP32_TO_GRAY_COEFFCIENT_6), GET_HIGH_ADDR(RGB_FP32_TO_GRAY_COEFFCIENT_6),
        GET_LOW_ADDR(RGB_FP32_TO_GRAY_COEFFCIENT_7), GET_HIGH_ADDR(RGB_FP32_TO_GRAY_COEFFCIENT_7),
        GET_LOW_ADDR(RGB_FP32_TO_GRAY_COEFFCIENT_8), GET_HIGH_ADDR(RGB_FP32_TO_GRAY_COEFFCIENT_8),
        GET_LOW_ADDR(RGB_FP32_TO_GRAY_OFFSET_0),     GET_HIGH_ADDR(RGB_FP32_TO_GRAY_OFFSET_0),
        GET_LOW_ADDR(RGB_FP32_TO_GRAY_OFFSET_1),     GET_HIGH_ADDR(RGB_FP32_TO_GRAY_OFFSET_1),
        GET_LOW_ADDR(RGB_FP32_TO_GRAY_OFFSET_2),     GET_HIGH_ADDR(RGB_FP32_TO_GRAY_OFFSET_2),
    },
    .pfn_judge_support = judge_support_rgbfp32_to_gray,
};
/******************************RGB_FP32_TO_GRAY******************************/

/***************************RGB_FP32_TO_GRAY_FP32***************************/
#define RGB_FP32_TO_GRAY_FP32_COEFFCIENT_0 0x0ULL
#define RGB_FP32_TO_GRAY_FP32_COEFFCIENT_1 0x0ULL
#define RGB_FP32_TO_GRAY_FP32_COEFFCIENT_2 0x0ULL
#define RGB_FP32_TO_GRAY_FP32_COEFFCIENT_3 0x0ULL
#define RGB_FP32_TO_GRAY_FP32_COEFFCIENT_4 0x0ULL
#define RGB_FP32_TO_GRAY_FP32_COEFFCIENT_5 0x0ULL
#define RGB_FP32_TO_GRAY_FP32_COEFFCIENT_6 0x3E99096CULL
#define RGB_FP32_TO_GRAY_FP32_COEFFCIENT_7 0x3F1645A2ULL
#define RGB_FP32_TO_GRAY_FP32_COEFFCIENT_8 0x3DE978D5ULL
#define RGB_FP32_TO_GRAY_FP32_OFFSET_0 0x0ULL
#define RGB_FP32_TO_GRAY_FP32_OFFSET_1 0x0ULL
#define RGB_FP32_TO_GRAY_FP32_OFFSET_2 0x0ULL

static uint8_t judge_support_rgbfp32_to_grayfp32(vpc_pic_fmt_e infmt, vpc_pic_fmt_e outfmt)
{
    return ((find_fmt(g_rgb_fp32_field, sizeof(g_rgb_fp32_field) / sizeof(vpc_pic_fmt_e), infmt)) &&
           (find_fmt(g_gray_fp32_field, sizeof(g_gray_fp32_field) / sizeof(vpc_pic_fmt_e), outfmt)));
}
static color_conv_t g_rgbfp32_to_grayfp32 = {
    .type = RGB_FP32_TO_GRAY_FP32,
    .coeff = {
        GET_LOW_ADDR(RGB_FP32_TO_GRAY_FP32_COEFFCIENT_0), GET_HIGH_ADDR(RGB_FP32_TO_GRAY_FP32_COEFFCIENT_0),
        GET_LOW_ADDR(RGB_FP32_TO_GRAY_FP32_COEFFCIENT_1), GET_HIGH_ADDR(RGB_FP32_TO_GRAY_FP32_COEFFCIENT_1),
        GET_LOW_ADDR(RGB_FP32_TO_GRAY_FP32_COEFFCIENT_2), GET_HIGH_ADDR(RGB_FP32_TO_GRAY_FP32_COEFFCIENT_2),
        GET_LOW_ADDR(RGB_FP32_TO_GRAY_FP32_COEFFCIENT_3), GET_HIGH_ADDR(RGB_FP32_TO_GRAY_FP32_COEFFCIENT_3),
        GET_LOW_ADDR(RGB_FP32_TO_GRAY_FP32_COEFFCIENT_4), GET_HIGH_ADDR(RGB_FP32_TO_GRAY_FP32_COEFFCIENT_4),
        GET_LOW_ADDR(RGB_FP32_TO_GRAY_FP32_COEFFCIENT_5), GET_HIGH_ADDR(RGB_FP32_TO_GRAY_FP32_COEFFCIENT_5),
        GET_LOW_ADDR(RGB_FP32_TO_GRAY_FP32_COEFFCIENT_6), GET_HIGH_ADDR(RGB_FP32_TO_GRAY_FP32_COEFFCIENT_6),
        GET_LOW_ADDR(RGB_FP32_TO_GRAY_FP32_COEFFCIENT_7), GET_HIGH_ADDR(RGB_FP32_TO_GRAY_FP32_COEFFCIENT_7),
        GET_LOW_ADDR(RGB_FP32_TO_GRAY_FP32_COEFFCIENT_8), GET_HIGH_ADDR(RGB_FP32_TO_GRAY_FP32_COEFFCIENT_8),
        GET_LOW_ADDR(RGB_FP32_TO_GRAY_FP32_OFFSET_0),     GET_HIGH_ADDR(RGB_FP32_TO_GRAY_FP32_OFFSET_0),
        GET_LOW_ADDR(RGB_FP32_TO_GRAY_FP32_OFFSET_1),     GET_HIGH_ADDR(RGB_FP32_TO_GRAY_FP32_OFFSET_1),
        GET_LOW_ADDR(RGB_FP32_TO_GRAY_FP32_OFFSET_2),     GET_HIGH_ADDR(RGB_FP32_TO_GRAY_FP32_OFFSET_2),
    },
    .pfn_judge_support = judge_support_rgbfp32_to_grayfp32,
};
/***************************RGB_FP32_TO_GRAY_FP32***************************/

/******************************RGB_FP32_TO_YUV******************************/
#define RGB_FP32_TO_YUV_COEFFCIENT_0 0x3E991687ULL
#define RGB_FP32_TO_YUV_COEFFCIENT_1 0x3F1645A1ULL
#define RGB_FP32_TO_YUV_COEFFCIENT_2 0x3DE978D4ULL
#define RGB_FP32_TO_YUV_COEFFCIENT_3 0x0ULL
#define RGB_FP32_TO_YUV_COEFFCIENT_4 0x0ULL
#define RGB_FP32_TO_YUV_COEFFCIENT_5 0x3EFBE76DULL
#define RGB_FP32_TO_YUV_COEFFCIENT_6 0x3F608311ULL
#define RGB_FP32_TO_YUV_COEFFCIENT_7 0x0ULL
#define RGB_FP32_TO_YUV_COEFFCIENT_8 0x0ULL
#define RGB_FP32_TO_YUV_OFFSET_0 0x0ULL
#define RGB_FP32_TO_YUV_OFFSET_1 0x3F000000ULL
#define RGB_FP32_TO_YUV_OFFSET_2 0x3F000000ULL

static uint8_t judge_support_rgbfp32_to_yuv(vpc_pic_fmt_e infmt, vpc_pic_fmt_e outfmt)
{
    return ((find_fmt(g_rgb_fp32_field, sizeof(g_rgb_fp32_field) / sizeof(vpc_pic_fmt_e), infmt)) &&
           (find_fmt(g_yuv_field, sizeof(g_yuv_field) / sizeof(vpc_pic_fmt_e), outfmt)));
}

static color_conv_t g_rgbfp32_to_yuv = {
    .type = RGB_FP32_TO_YUV,
    .coeff = {
        GET_LOW_ADDR(RGB_FP32_TO_YUV_COEFFCIENT_0), GET_HIGH_ADDR(RGB_FP32_TO_YUV_COEFFCIENT_0),
        GET_LOW_ADDR(RGB_FP32_TO_YUV_COEFFCIENT_1), GET_HIGH_ADDR(RGB_FP32_TO_YUV_COEFFCIENT_1),
        GET_LOW_ADDR(RGB_FP32_TO_YUV_COEFFCIENT_2), GET_HIGH_ADDR(RGB_FP32_TO_YUV_COEFFCIENT_2),
        GET_LOW_ADDR(RGB_FP32_TO_YUV_COEFFCIENT_3), GET_HIGH_ADDR(RGB_FP32_TO_YUV_COEFFCIENT_3),
        GET_LOW_ADDR(RGB_FP32_TO_YUV_COEFFCIENT_4), GET_HIGH_ADDR(RGB_FP32_TO_YUV_COEFFCIENT_4),
        GET_LOW_ADDR(RGB_FP32_TO_YUV_COEFFCIENT_5), GET_HIGH_ADDR(RGB_FP32_TO_YUV_COEFFCIENT_5),
        GET_LOW_ADDR(RGB_FP32_TO_YUV_COEFFCIENT_6), GET_HIGH_ADDR(RGB_FP32_TO_YUV_COEFFCIENT_6),
        GET_LOW_ADDR(RGB_FP32_TO_YUV_COEFFCIENT_7), GET_HIGH_ADDR(RGB_FP32_TO_YUV_COEFFCIENT_7),
        GET_LOW_ADDR(RGB_FP32_TO_YUV_COEFFCIENT_8), GET_HIGH_ADDR(RGB_FP32_TO_YUV_COEFFCIENT_8),
        GET_LOW_ADDR(RGB_FP32_TO_YUV_OFFSET_0),     GET_HIGH_ADDR(RGB_FP32_TO_YUV_OFFSET_0),
        GET_LOW_ADDR(RGB_FP32_TO_YUV_OFFSET_1),     GET_HIGH_ADDR(RGB_FP32_TO_YUV_OFFSET_1),
        GET_LOW_ADDR(RGB_FP32_TO_YUV_OFFSET_2),     GET_HIGH_ADDR(RGB_FP32_TO_YUV_OFFSET_2),
    },
    .pfn_judge_support = judge_support_rgbfp32_to_yuv,
};
/******************************RGB_FP32_TO_YUV******************************/

/******************************YUV_FP32_TO_RGB******************************/
#define YUV_FP32_TO_RGB_COEFFCIENT_0 0x3F91EB85ULL
#define YUV_FP32_TO_RGB_COEFFCIENT_1 0x0ULL
#define YUV_FP32_TO_RGB_COEFFCIENT_2 0x3F800000ULL
#define YUV_FP32_TO_RGB_COEFFCIENT_3 0xBF14BC69ULL
#define YUV_FP32_TO_RGB_COEFFCIENT_4 0xBECA3D71ULL
#define YUV_FP32_TO_RGB_COEFFCIENT_5 0x3F800000ULL
#define YUV_FP32_TO_RGB_COEFFCIENT_6 0x0ULL
#define YUV_FP32_TO_RGB_COEFFCIENT_7 0x40020C49ULL
#define YUV_FP32_TO_RGB_COEFFCIENT_8 0x3F800000ULL
#define YUV_FP32_TO_RGB_OFFSET_0 0xBF000000ULL
#define YUV_FP32_TO_RGB_OFFSET_1 0xBF000000ULL
#define YUV_FP32_TO_RGB_OFFSET_2 0x0ULL

static uint8_t judge_support_yuvfp32_to_rgb(vpc_pic_fmt_e infmt, vpc_pic_fmt_e outfmt)
{
    return 0;
}

static color_conv_t g_yuvfp32_to_rgb = {
    .type = YUV_FP32_TO_RGB,
    .coeff = {
        GET_LOW_ADDR(YUV_FP32_TO_RGB_COEFFCIENT_0), GET_HIGH_ADDR(YUV_FP32_TO_RGB_COEFFCIENT_0),
        GET_LOW_ADDR(YUV_FP32_TO_RGB_COEFFCIENT_1), GET_HIGH_ADDR(YUV_FP32_TO_RGB_COEFFCIENT_1),
        GET_LOW_ADDR(YUV_FP32_TO_RGB_COEFFCIENT_2), GET_HIGH_ADDR(YUV_FP32_TO_RGB_COEFFCIENT_2),
        GET_LOW_ADDR(YUV_FP32_TO_RGB_COEFFCIENT_3), GET_HIGH_ADDR(YUV_FP32_TO_RGB_COEFFCIENT_3),
        GET_LOW_ADDR(YUV_FP32_TO_RGB_COEFFCIENT_4), GET_HIGH_ADDR(YUV_FP32_TO_RGB_COEFFCIENT_4),
        GET_LOW_ADDR(YUV_FP32_TO_RGB_COEFFCIENT_5), GET_HIGH_ADDR(YUV_FP32_TO_RGB_COEFFCIENT_5),
        GET_LOW_ADDR(YUV_FP32_TO_RGB_COEFFCIENT_6), GET_HIGH_ADDR(YUV_FP32_TO_RGB_COEFFCIENT_6),
        GET_LOW_ADDR(YUV_FP32_TO_RGB_COEFFCIENT_7), GET_HIGH_ADDR(YUV_FP32_TO_RGB_COEFFCIENT_7),
        GET_LOW_ADDR(YUV_FP32_TO_RGB_COEFFCIENT_8), GET_HIGH_ADDR(YUV_FP32_TO_RGB_COEFFCIENT_8),
        GET_LOW_ADDR(YUV_FP32_TO_RGB_OFFSET_0),     GET_HIGH_ADDR(YUV_FP32_TO_RGB_OFFSET_0),
        GET_LOW_ADDR(YUV_FP32_TO_RGB_OFFSET_1),     GET_HIGH_ADDR(YUV_FP32_TO_RGB_OFFSET_1),
        GET_LOW_ADDR(YUV_FP32_TO_RGB_OFFSET_2),     GET_HIGH_ADDR(YUV_FP32_TO_RGB_OFFSET_2),
    },
    .pfn_judge_support = judge_support_yuvfp32_to_rgb,
};
/******************************YUV_FP32_TO_RGB******************************/

/******************************YUV_FP32_TO_GRAY******************************/
#define YUV_FP32_TO_GRAY_COEFFCIENT_0 0x0ULL
#define YUV_FP32_TO_GRAY_COEFFCIENT_1 0x0ULL
#define YUV_FP32_TO_GRAY_COEFFCIENT_2 0x0ULL
#define YUV_FP32_TO_GRAY_COEFFCIENT_3 0x0ULL
#define YUV_FP32_TO_GRAY_COEFFCIENT_4 0x0ULL
#define YUV_FP32_TO_GRAY_COEFFCIENT_5 0x0ULL
#define YUV_FP32_TO_GRAY_COEFFCIENT_6 0x3F800000ULL
#define YUV_FP32_TO_GRAY_COEFFCIENT_7 0x0ULL
#define YUV_FP32_TO_GRAY_COEFFCIENT_8 0x0ULL
#define YUV_FP32_TO_GRAY_OFFSET_0 0x0ULL
#define YUV_FP32_TO_GRAY_OFFSET_1 0x0ULL
#define YUV_FP32_TO_GRAY_OFFSET_2 0x0ULL

static uint8_t judge_support_yuvfp32_to_gray(vpc_pic_fmt_e infmt, vpc_pic_fmt_e outfmt)
{
    return 0;
}

static color_conv_t g_yuvfp32_to_gray = {
    .type = YUV_FP32_TO_GRAY,
    .coeff = {
        GET_LOW_ADDR(YUV_FP32_TO_GRAY_COEFFCIENT_0), GET_HIGH_ADDR(YUV_FP32_TO_GRAY_COEFFCIENT_0),
        GET_LOW_ADDR(YUV_FP32_TO_GRAY_COEFFCIENT_1), GET_HIGH_ADDR(YUV_FP32_TO_GRAY_COEFFCIENT_1),
        GET_LOW_ADDR(YUV_FP32_TO_GRAY_COEFFCIENT_2), GET_HIGH_ADDR(YUV_FP32_TO_GRAY_COEFFCIENT_2),
        GET_LOW_ADDR(YUV_FP32_TO_GRAY_COEFFCIENT_3), GET_HIGH_ADDR(YUV_FP32_TO_GRAY_COEFFCIENT_3),
        GET_LOW_ADDR(YUV_FP32_TO_GRAY_COEFFCIENT_4), GET_HIGH_ADDR(YUV_FP32_TO_GRAY_COEFFCIENT_4),
        GET_LOW_ADDR(YUV_FP32_TO_GRAY_COEFFCIENT_5), GET_HIGH_ADDR(YUV_FP32_TO_GRAY_COEFFCIENT_5),
        GET_LOW_ADDR(YUV_FP32_TO_GRAY_COEFFCIENT_6), GET_HIGH_ADDR(YUV_FP32_TO_GRAY_COEFFCIENT_6),
        GET_LOW_ADDR(YUV_FP32_TO_GRAY_COEFFCIENT_7), GET_HIGH_ADDR(YUV_FP32_TO_GRAY_COEFFCIENT_7),
        GET_LOW_ADDR(YUV_FP32_TO_GRAY_COEFFCIENT_8), GET_HIGH_ADDR(YUV_FP32_TO_GRAY_COEFFCIENT_8),
        GET_LOW_ADDR(YUV_FP32_TO_GRAY_OFFSET_0),     GET_HIGH_ADDR(YUV_FP32_TO_GRAY_OFFSET_0),
        GET_LOW_ADDR(YUV_FP32_TO_GRAY_OFFSET_1),     GET_HIGH_ADDR(YUV_FP32_TO_GRAY_OFFSET_1),
        GET_LOW_ADDR(YUV_FP32_TO_GRAY_OFFSET_2),     GET_HIGH_ADDR(YUV_FP32_TO_GRAY_OFFSET_2),
    },
    .pfn_judge_support = judge_support_yuvfp32_to_gray,
};
/******************************YUV_FP32_TO_GRAY******************************/

/******************************GRAY_FP32_TO_RGB******************************/
#define GRAY_FP32_TO_RGB_COEFFCIENT_0 0x0ULL
#define GRAY_FP32_TO_RGB_COEFFCIENT_1 0x0ULL
#define GRAY_FP32_TO_RGB_COEFFCIENT_2 0x3F800000ULL
#define GRAY_FP32_TO_RGB_COEFFCIENT_3 0x0ULL
#define GRAY_FP32_TO_RGB_COEFFCIENT_4 0x0ULL
#define GRAY_FP32_TO_RGB_COEFFCIENT_5 0x3F800000ULL
#define GRAY_FP32_TO_RGB_COEFFCIENT_6 0x0ULL
#define GRAY_FP32_TO_RGB_COEFFCIENT_7 0x0ULL
#define GRAY_FP32_TO_RGB_COEFFCIENT_8 0x3F800000ULL
#define GRAY_FP32_TO_RGB_OFFSET_0 0x0ULL
#define GRAY_FP32_TO_RGB_OFFSET_1 0x0ULL
#define GRAY_FP32_TO_RGB_OFFSET_2 0x0ULL

static uint8_t judge_support_grayfp32_to_rgb(vpc_pic_fmt_e infmt, vpc_pic_fmt_e outfmt)
{
    return ((find_fmt(g_gray_fp32_field, sizeof(g_gray_fp32_field) / sizeof(vpc_pic_fmt_e), infmt)) &&
           (find_fmt(g_rgb_field, sizeof(g_rgb_field) / sizeof(vpc_pic_fmt_e), outfmt)));
}

static color_conv_t g_grayfp32_to_rgb = {
    .type = GRAY_FP32_TO_RGB,
    .coeff = {
        GET_LOW_ADDR(GRAY_FP32_TO_RGB_COEFFCIENT_0), GET_HIGH_ADDR(GRAY_FP32_TO_RGB_COEFFCIENT_0),
        GET_LOW_ADDR(GRAY_FP32_TO_RGB_COEFFCIENT_1), GET_HIGH_ADDR(GRAY_FP32_TO_RGB_COEFFCIENT_1),
        GET_LOW_ADDR(GRAY_FP32_TO_RGB_COEFFCIENT_2), GET_HIGH_ADDR(GRAY_FP32_TO_RGB_COEFFCIENT_2),
        GET_LOW_ADDR(GRAY_FP32_TO_RGB_COEFFCIENT_3), GET_HIGH_ADDR(GRAY_FP32_TO_RGB_COEFFCIENT_3),
        GET_LOW_ADDR(GRAY_FP32_TO_RGB_COEFFCIENT_4), GET_HIGH_ADDR(GRAY_FP32_TO_RGB_COEFFCIENT_4),
        GET_LOW_ADDR(GRAY_FP32_TO_RGB_COEFFCIENT_5), GET_HIGH_ADDR(GRAY_FP32_TO_RGB_COEFFCIENT_5),
        GET_LOW_ADDR(GRAY_FP32_TO_RGB_COEFFCIENT_6), GET_HIGH_ADDR(GRAY_FP32_TO_RGB_COEFFCIENT_6),
        GET_LOW_ADDR(GRAY_FP32_TO_RGB_COEFFCIENT_7), GET_HIGH_ADDR(GRAY_FP32_TO_RGB_COEFFCIENT_7),
        GET_LOW_ADDR(GRAY_FP32_TO_RGB_COEFFCIENT_8), GET_HIGH_ADDR(GRAY_FP32_TO_RGB_COEFFCIENT_8),
        GET_LOW_ADDR(GRAY_FP32_TO_RGB_OFFSET_0),     GET_HIGH_ADDR(GRAY_FP32_TO_RGB_OFFSET_0),
        GET_LOW_ADDR(GRAY_FP32_TO_RGB_OFFSET_1),     GET_HIGH_ADDR(GRAY_FP32_TO_RGB_OFFSET_1),
        GET_LOW_ADDR(GRAY_FP32_TO_RGB_OFFSET_2),     GET_HIGH_ADDR(GRAY_FP32_TO_RGB_OFFSET_2),
    },
    .pfn_judge_support = judge_support_grayfp32_to_rgb,
};
/******************************GRAY_FP32_TO_RGB******************************/

/******************************GRAY_FP32_TO_YUV******************************/
#define GRAY_FP32_TO_YUV_COEFFCIENT_0 0x0ULL
#define GRAY_FP32_TO_YUV_COEFFCIENT_1 0x0ULL
#define GRAY_FP32_TO_YUV_COEFFCIENT_2 0x3F800000ULL
#define GRAY_FP32_TO_YUV_COEFFCIENT_3 0x0ULL
#define GRAY_FP32_TO_YUV_COEFFCIENT_4 0x0ULL
#define GRAY_FP32_TO_YUV_COEFFCIENT_5 0x0ULL
#define GRAY_FP32_TO_YUV_COEFFCIENT_6 0x0ULL
#define GRAY_FP32_TO_YUV_COEFFCIENT_7 0x0ULL
#define GRAY_FP32_TO_YUV_COEFFCIENT_8 0x0ULL
#define GRAY_FP32_TO_YUV_OFFSET_0 0x0ULL
#define GRAY_FP32_TO_YUV_OFFSET_1 0x43000000ULL
#define GRAY_FP32_TO_YUV_OFFSET_2 0x43000000ULL

static uint8_t judge_support_grayfp32_to_yuv(vpc_pic_fmt_e infmt, vpc_pic_fmt_e outfmt)
{
    return ((find_fmt(g_gray_fp32_field, sizeof(g_gray_fp32_field) / sizeof(vpc_pic_fmt_e), infmt)) &&
           (find_fmt(g_yuv_field, sizeof(g_yuv_field) / sizeof(vpc_pic_fmt_e), outfmt)));
}

static color_conv_t g_grayfp32_to_yuv = {
    .type = GRAY_FP32_TO_YUV,
    .coeff = {
        GET_LOW_ADDR(GRAY_FP32_TO_YUV_COEFFCIENT_0), GET_HIGH_ADDR(GRAY_FP32_TO_YUV_COEFFCIENT_0),
        GET_LOW_ADDR(GRAY_FP32_TO_YUV_COEFFCIENT_1), GET_HIGH_ADDR(GRAY_FP32_TO_YUV_COEFFCIENT_1),
        GET_LOW_ADDR(GRAY_FP32_TO_YUV_COEFFCIENT_2), GET_HIGH_ADDR(GRAY_FP32_TO_YUV_COEFFCIENT_2),
        GET_LOW_ADDR(GRAY_FP32_TO_YUV_COEFFCIENT_3), GET_HIGH_ADDR(GRAY_FP32_TO_YUV_COEFFCIENT_3),
        GET_LOW_ADDR(GRAY_FP32_TO_YUV_COEFFCIENT_4), GET_HIGH_ADDR(GRAY_FP32_TO_YUV_COEFFCIENT_4),
        GET_LOW_ADDR(GRAY_FP32_TO_YUV_COEFFCIENT_5), GET_HIGH_ADDR(GRAY_FP32_TO_YUV_COEFFCIENT_5),
        GET_LOW_ADDR(GRAY_FP32_TO_YUV_COEFFCIENT_6), GET_HIGH_ADDR(GRAY_FP32_TO_YUV_COEFFCIENT_6),
        GET_LOW_ADDR(GRAY_FP32_TO_YUV_COEFFCIENT_7), GET_HIGH_ADDR(GRAY_FP32_TO_YUV_COEFFCIENT_7),
        GET_LOW_ADDR(GRAY_FP32_TO_YUV_COEFFCIENT_8), GET_HIGH_ADDR(GRAY_FP32_TO_YUV_COEFFCIENT_8),
        GET_LOW_ADDR(GRAY_FP32_TO_YUV_OFFSET_0),     GET_HIGH_ADDR(GRAY_FP32_TO_YUV_OFFSET_0),
        GET_LOW_ADDR(GRAY_FP32_TO_YUV_OFFSET_1),     GET_HIGH_ADDR(GRAY_FP32_TO_YUV_OFFSET_1),
        GET_LOW_ADDR(GRAY_FP32_TO_YUV_OFFSET_2),     GET_HIGH_ADDR(GRAY_FP32_TO_YUV_OFFSET_2),
    },
    .pfn_judge_support = judge_support_grayfp32_to_yuv,
};
/******************************GRAY_FP32_TO_YUV******************************/
static void get_yuv_to_rgb_coeff(
    color_conv_t *conv, uint32_t csc_coeff[CSC_COEFF_NUM], const vpc_pipe_csc_info_t *info)
{
    uint32_t index;
    uint64_t value;
    for (index = 0; index < CSC_COEFF_NUM; index++) {
        if (info->csc_matrix != VPC_PIPE_CSC_MATRIX_USER) {
            value = VUY_TO_BGR_COEFF[info->csc_matrix][index / NUM_2];
        } else {
            value = (uint64_t)(info->csc_coeff.yuv_to_rgb_coeff[index / NUM_2]);
        }
        if (index % NUM_2 == 0) {
            csc_coeff[index] = GET_LOW_ADDR(value);
        } else {
            csc_coeff[index] = GET_HIGH_ADDR(value);
        }
    }
}

static void get_rgb_to_yuv_coeff(
    color_conv_t *conv, uint32_t csc_coeff[CSC_COEFF_NUM], const vpc_pipe_csc_info_t *info)
{
    uint32_t index;
    uint64_t value;
    for (index = 0; index < CSC_COEFF_NUM; index++) {
        if (info->csc_matrix != VPC_PIPE_CSC_MATRIX_USER) {
            value = RGB_TO_YUV_COEFF[info->csc_matrix][index / NUM_2];
        } else {
            value = (uint64_t)(info->csc_coeff.rgb_to_yuv_coeff[index / NUM_2]);
        }
        if (index % NUM_2 == 0) {
            csc_coeff[index] = GET_LOW_ADDR(value);
        } else {
            csc_coeff[index] = GET_HIGH_ADDR(value);
        }
    }
}

static void get_rgb_to_gray_coeff(
    color_conv_t *conv, uint32_t csc_coeff[CSC_COEFF_NUM], const vpc_pipe_csc_info_t *info)
{
    uint32_t index;
    uint64_t value;
    for (index = 0; index < CSC_COEFF_NUM; index++) {
        if (info->csc_matrix != VPC_PIPE_CSC_MATRIX_USER) {
            csc_coeff[index] = conv->coeff[index];
        } else {
            value = (uint64_t)(info->csc_coeff.rgb_to_yuv_coeff[index / NUM_2]);
            if (index % NUM_2 == 0) {
                csc_coeff[index] = GET_LOW_ADDR(value);
            } else {
                csc_coeff[index] = GET_HIGH_ADDR(value);
            }
        }
    }
}

void get_csc_coeff(color_conv_t *conv, uint32_t csc_coeff[CSC_COEFF_NUM], const vpc_pipe_csc_info_t *info)
{
    if (conv->type == YUV_TO_RGB) {
        get_yuv_to_rgb_coeff(conv, csc_coeff, info);
    } else if (conv->type == RGB_TO_YUV) {
        get_rgb_to_yuv_coeff(conv, csc_coeff, info);
    } else if (conv->type == RGB_TO_GRAY) {
        get_rgb_to_gray_coeff(conv, csc_coeff, info);
    } else {
        uint32_t index;
        for (index = 0; index < CSC_COEFF_NUM; index++) {
            csc_coeff[index] = conv->coeff[index];
        }
    }
}

uint8_t judge_u8_field(vpc_pic_fmt_e fmt)
{
    return ((find_fmt(g_yuv_field, sizeof(g_yuv_field) / sizeof(vpc_pic_fmt_e), fmt)) ||
           (find_fmt(g_rgb_field, sizeof(g_rgb_field) / sizeof(vpc_pic_fmt_e), fmt)) ||
           (find_fmt(g_gray_field, sizeof(g_gray_field) / sizeof(vpc_pic_fmt_e), fmt)));
}

uint8_t judge_fp_field(vpc_pic_fmt_e fmt)
{
    return ((find_fmt(g_rgb_fp32_field, sizeof(g_rgb_fp32_field) / sizeof(vpc_pic_fmt_e), fmt)) ||
           (find_fmt(g_gray_fp32_field, sizeof(g_gray_fp32_field) / sizeof(vpc_pic_fmt_e), fmt)));
}

uint8_t judge_fp32_field(vpc_pic_fmt_e fmt)
{
    return find_fmt(g_fp32_field, sizeof(g_fp32_field) / sizeof(vpc_pic_fmt_e), fmt);
}

static uint8_t judge_yuv422_cscfmt(vpc_pic_fmt_e infmt, vpc_pic_fmt_e outfmt)
{
    if (infmt == YUV422_SEMI_PLANNAR || infmt == YUV422_PLANNAR || infmt == YUV422_PACKED) {
        if (outfmt == YUV420_SEMI_PLANNAR || outfmt == YUV422_SEMI_PLANNAR ||
            outfmt == YUV422_PLANNAR || outfmt == YUV422_PACKED) {
            return 1;
        }
    }

    return 0;
}

static uint8_t judge_enable_float_cal(vpc_pic_fmt_e infmt, vpc_pic_fmt_e outfmt)
{
    if (judge_yuv422_cscfmt(infmt, outfmt)) {
        return 0;
    }

    if (infmt != outfmt) {
        if (!judge_u8_field(infmt) || !(judge_u8_field(outfmt) || judge_fp32_field(outfmt))) {
            return 1;
        }
    }

    return 0;
}

csc_mode_t get_csc_mode(color_conv_t *conv, vpc_pic_fmt_e infmt, vpc_pic_fmt_e outfmt)
{
    csc_mode_t mode = {0};
    if (conv->type == RGB_FP32_TO_YUV) {
        mode.calCore = judge_enable_float_cal(infmt, outfmt);
        mode.yForward = 1;
        mode.fpOrder = 1;
        return mode;
    }

    mode.calCore = judge_enable_float_cal(infmt, outfmt);
    return mode;
}

csc_mode_t get_data_cvt_csc_mode(vpc_pic_fmt_e infmt, vpc_pic_fmt_e outfmt)
{
    csc_mode_t mode = {0};
    mode.calCore = judge_enable_float_cal(infmt, outfmt);
    return mode;
}

color_conv_t* get_color_conv(vpc_pic_fmt_e infmt, vpc_pic_fmt_e outfmt)
{
    uint32_t index;
    static color_conv_t* all_color_conv[CSC_TYPE_BUTT] = {
        &g_yuv_to_rgb,
        &g_rgb_to_yuv,
        &g_rgb_to_gray,
        &g_gray_to_rgb,
        &g_yuv_to_gray,
        &g_gray_to_yuv,
        &g_rgbfp32_to_gray,
        &g_rgbfp32_to_yuv,
        &g_yuvfp32_to_rgb,
        &g_yuvfp32_to_gray,
        &g_grayfp32_to_rgb,
        &g_grayfp32_to_yuv,
        &g_rgbfp32_to_grayfp32,
    };

    for (index = 0; index < CSC_TYPE_BUTT; index++) {
        if ((all_color_conv[index]->pfn_judge_support(infmt, outfmt)) == 1) {
            return all_color_conv[index];
        }
    }

    return NULL;
}
